Should now handle all formats, slow routine used where optimised
authorMichael Zucchi <zucchi@zedzone.mmc.com.au>
Thu, 9 Dec 1999 01:50:18 +0000 (01:50 +0000)
committerMichael Zucci <zucchi@src.gnome.org>
Thu, 9 Dec 1999 01:50:18 +0000 (01:50 +0000)
ones can't be.

1999-12-09  Michael Zucchi  <zucchi@zedzone.mmc.com.au>

        * gdk-pixbuf/gdk-pixbuf-drawable.c
        (convert_real_slow): New function - should convert ANY visual/data
        format properly, but it aint fast.  Used as a fallback when an
        optimised routine wont match.
        (rgbconvert): Do very specific tests on the data format to verify
        properly if the optimised version will do, otherwise use the
        fallback function for all other data formats.

gdk-pixbuf/ChangeLog
gdk/gdkpixbuf-drawable.c

index 3e2b18086ed962a5ff33031e12611ac026cda196..e9a1e76967bbf1b67f5b1fe761a8a18d77e82607 100644 (file)
@@ -4,6 +4,12 @@
        Filled in body of function.
        (rgbconvert): Added GdkColormap parameter, and to all conversion
        functions also.
+       (convert_real_slow): New function - should convert ANY visual/data
+       format properly, but it aint fast.  Used as a fallback when an
+       optimised routine wont match.
+       (rgbconvert): Do very specific tests on the data format to verify
+       properly if the optimised version will do, otherwise use the
+       fallback function for all other data formats.
 
        * gdk-pixbuf/Makefile.am: Re-enabled building of
        textpixbuf-drawable.
index ad519f045dc1747eb657bd78f3c05b5952b03943..35d829bff69d7b92d8beaee9fdf8a437a2c56213 100644 (file)
@@ -836,6 +836,69 @@ rgb888msb (GdkImage *image, art_u8 *pixels, int rowstride, GdkColormap *colormap
        }
 }
 
+/*
+  This should work correctly with any display/any endianness, but will probably
+  run quite slow
+*/
+static void
+convert_real_slow (GdkImage *image, art_u8 *pixels, int rowstride, GdkColormap *cmap, int alpha)
+{
+       int xx, yy;
+       int width, height;
+       int bpl;
+       unsigned char *srow = image->mem, *orow = pixels;
+       unsigned char *s;
+       unsigned char *o;
+       guint32 pixel;
+       GdkVisual *v;
+
+       width = image->width;
+       height = image->height;
+       bpl = image->bpl;
+       v = gdk_colormap_get_visual(cmap);
+
+       d(printf("rgb  mask/shift/prec = %x:%x:%x %d:%d:%d  %d:%d:%d\n",
+                v->red_mask, v->green_mask, v->blue_mask,
+                v->red_shift, v->green_shift, v->blue_shift,
+                v->red_prec, v->green_prec, v->blue_prec));
+
+       for (yy = 0; yy < height; yy++) {
+               s = srow;
+               o = orow;
+               for (xx = 0; xx < width; xx++) {
+                       pixel = gdk_image_get_pixel(image, xx, yy);
+                       switch (v->type) {
+                               /* I assume this is right for static & greyscale's too? */
+                       case GDK_VISUAL_STATIC_GRAY:
+                       case GDK_VISUAL_GRAYSCALE:
+                       case GDK_VISUAL_STATIC_COLOR:
+                       case GDK_VISUAL_PSEUDO_COLOR:
+                               *o++ = cmap->colors[pixel].red;
+                               *o++ = cmap->colors[pixel].green;
+                               *o++ = cmap->colors[pixel].blue;
+                               break;
+                       case GDK_VISUAL_TRUE_COLOR:
+                               /* this is odd because it must sometimes shift left (otherwise
+                                  i'd just shift >> *_shift - 8 + *_prec), so this logic
+                                  should work for all bit sizes/shifts/etc */
+                               *o++ = ((pixel & v->red_mask) << (32 - v->red_shift - v->red_prec)) >> 24;
+                               *o++ = ((pixel & v->green_mask) << (32 - v->green_shift - v->green_prec)) >> 24;
+                               *o++ = ((pixel & v->blue_mask) << (32 - v->blue_shift - v->blue_prec)) >> 24;
+                               break;
+                       case GDK_VISUAL_DIRECT_COLOR:
+                               *o++ = cmap->colors[((pixel & v->red_mask) << (32 - v->red_shift - v->red_prec)) >> 24].red;
+                               *o++ = cmap->colors[((pixel & v->green_mask) << (32 - v->green_shift - v->green_prec)) >> 24].green;
+                               *o++ = cmap->colors[((pixel & v->blue_mask) << (32 - v->blue_shift - v->blue_prec)) >> 24].blue;
+                               break;
+                       }
+                       if (alpha)
+                               *o++ = 0xff;
+               }
+               srow += bpl;
+               orow += rowstride;
+       }
+}
+
 typedef void (* cfunc) (GdkImage *image, art_u8 *pixels, int rowstride, GdkColormap *cmap);
 
 static cfunc convert_map[] = {
@@ -848,38 +911,69 @@ static cfunc convert_map[] = {
 
 /*
   perform actual conversion
+
+  If we can, try and use the optimised code versions, but as a default
+  fallback, and always for direct colour, use the generic/slow but complete
+  conversion function.
 */
 static void
 rgbconvert (GdkImage *image, art_u8 *pixels, int rowstride, int alpha, GdkColormap *cmap)
 {
        int index = (image->byte_order == GDK_MSB_FIRST) | (alpha != 0) << 1;
-       int bank=0;
-
-       switch (image->depth) {
-       case 1:
-               bank = 0;
+       int bank=5;             /* default fallback converter */
+       GdkVisual *v = gdk_colormap_get_visual(cmap);
+
+       d(printf("masks = %x:%x:%x\n", v->red_mask, v->green_mask, v->blue_mask));
+       d(printf("image depth = %d, bpp = %d\n", image->depth, image->bpp));
+
+       switch (v->type) {
+                               /* I assume this is right for static & greyscale's too? */
+       case GDK_VISUAL_STATIC_GRAY:
+       case GDK_VISUAL_GRAYSCALE:
+       case GDK_VISUAL_STATIC_COLOR:
+       case GDK_VISUAL_PSEUDO_COLOR:
+               switch (image->bpp) {
+               case 1:
+                       bank = 0;
+                       break;
+               case 8:
+                       bank = 1;
+                       break;
+               }
                break;
-
-       case 8:
-               bank = 1;
+       case GDK_VISUAL_TRUE_COLOR:
+               switch (image->depth) {
+               case 15:
+                       if (v->red_mask == 0x7c00 && v->green_mask == 0x3e0 && v->blue_mask == 0x1f
+                           && image->bpp == 16)
+                               bank = 2;
+                       break;
+               case 16:
+                       if (v->red_mask == 0xf800 && v->green_mask == 0x7e0 && v->blue_mask == 0x1f
+                           && image->bpp == 16)
+                               bank = 3;
+                       break;                  
+               case 24:
+               case 32:
+                       if (v->red_mask == 0xff0000 && v->green_mask == 0xff00 && v->blue_mask == 0xff
+                           && image->bpp == 32)
+                               bank = 4;
+                       break;
+               }
                break;
-
-       case 15:
-               bank = 2;
+       case GDK_VISUAL_DIRECT_COLOR:
+               /* always use the slow version */
                break;
+       }
 
-       case 16:
-               bank = 3;
-               break;
+       d(printf("converting using conversion function in bank %d\n", bank));
 
-       case 24:
-       case 32:
-               bank = 4;
-               break;
+       if (bank==5) {
+               convert_real_slow(image, pixels, rowstride, cmap, alpha);
+       } else {
+               index |= bank << 2;
+               (* convert_map[index]) (image, pixels, rowstride, cmap);
        }
-
-       index |= bank << 2;
-       (* convert_map[index]) (image, pixels, rowstride, cmap);
 }